﻿using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using HengTong.Model.Extension;
using HengTong.Model.Request;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TiaoTaoHelper.Models;
using WalkingTec.Mvvm.Core;
using System.Collections.Generic;
using AlibabaCloud.OpenApiClient.Models;
using AlibabaCloud.TeaUtil.Models;

namespace HengTong.Model.Services;

public interface IIdentityCardRecognitionService
{
    Task<Result<IdentityCardInfo>> RecognizeOldAsync(Guid ImageId, string cardType = "front");
    Task<Result<IdentityCardInfo>> RecognizeAsync(Guid ImageId, string cardType = "front");
}

public class IdentityCardRecognitionService : IIdentityCardRecognitionService
{
    private readonly WTMContext _context;
    private readonly ILogger<IdentityCardRecognitionService> _logger;
    private readonly HttpClient _httpClient;

    public IdentityCardRecognitionService(WTMContext context, ILogger<IdentityCardRecognitionService> logger,
        HttpClient httpClient)
    {
        _context = context;
        _logger = logger;
        _httpClient = httpClient;
    }

    // 阿里身份证OCR文字识别：https://market.aliyun.com/apimarket/detail/cmapi010401#sku=yuncode4401000018
    public async Task<Result<IdentityCardInfo>> RecognizeOldAsync(Guid ImageId, string cardType = "front")
    {
        try
        {
            _logger.LogInformation($"开始识别身份证（旧版），ImageId: {ImageId}, cardType: {cardType}");

            var scope = _context.ServiceProvider.CreateScope();
            var dc = scope.ServiceProvider.GetRequiredService<WTMContext>().DC;

            // 根据图片ID获取图片文件
            var fileAttachment = await dc.Set<FileAttachment>()
                .AsNoTracking()
                .FirstOrDefaultAsync(f => f.ID == ImageId);
            if (fileAttachment == null)
            {
                _logger.LogWarning($"未找到图片，ImageId: {ImageId}");
                return new Result<IdentityCardInfo>("图片不存在");
            }

            byte[] imageData = null;
            
            _logger.LogInformation($"图片存储模式: {fileAttachment.SaveMode}");
            // 根据存储类型获取图片数据
            if (string.Equals(fileAttachment.SaveMode, "database", StringComparison.OrdinalIgnoreCase))
            {
                // 数据库存储模式
                if (fileAttachment.FileData == null || fileAttachment.FileData.Length == 0)
                {
                    _logger.LogWarning($"数据库存储的图片内容为空，ImageId: {ImageId}");
                    return new Result<IdentityCardInfo>("数据库存储的图片内容为空");
                }

                imageData = fileAttachment.FileData;
            }
            else if (string.Equals(fileAttachment.SaveMode, "local", StringComparison.OrdinalIgnoreCase))
            {
                // 本地文件存储模式
                if (string.IsNullOrEmpty(fileAttachment.Path))
                {
                    _logger.LogWarning($"本地存储的图片路径为空，ImageId: {ImageId}");
                    return new Result<IdentityCardInfo>("本地存储的图片路径为空");
                }

                var fullPath = Path.IsPathRooted(fileAttachment.Path)
                    ? fileAttachment.Path
                    : Path.Combine(Directory.GetCurrentDirectory(), fileAttachment.Path);

                if (!File.Exists(fullPath))
                {
                    _logger.LogWarning($"本地图片文件不存在，路径: {fullPath}");
                    return new Result<IdentityCardInfo>($"本地图片文件不存在: {fileAttachment.Path}");
                }

                try
                {
                    imageData = await File.ReadAllBytesAsync(fullPath);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, $"读取本地图片文件失败，路径: {fullPath}");
                    return new Result<IdentityCardInfo>($"读取本地图片文件失败: {ex.Message}");
                }
            }
            else
            {
                _logger.LogWarning($"不支持的存储模式: {fileAttachment.SaveMode}，ImageId: {ImageId}");
                return new Result<IdentityCardInfo>($"不支持的存储模式: {fileAttachment.SaveMode}");
            }

            if (imageData == null || imageData.Length == 0)
            {
                _logger.LogWarning($"获取到的图片数据为空，ImageId: {ImageId}");
                return new Result<IdentityCardInfo>("图片数据为空");
            }

            // 转换为纯Base64字符串（不包含data URL前缀）
            var imageBase64 = Convert.ToBase64String(imageData);
            // fileAttachment转换为Base64字符串
            //var imageBase64 = $"data:image/{fileAttachment.FileExt.TrimStart('.')};base64,{Convert.ToBase64String(fileAttachment.FileData)}";

            // 从站点配置表中获取阿里云OCR配置
            var siteConfig = _context.GetSiteConfig();
            var appCode = siteConfig.AliyunOcrAppCode;

            if (string.IsNullOrEmpty(appCode))
            {
                return new Result<IdentityCardInfo>("阿里云OCR配置不完整，请在系统设置中配置AppCode");
            }

            // 记录配置信息（可选）
            _logger.LogInformation($"使用阿里云OCR服务 -  AppCode: {appCode}");

            // 阿里云市场OCR接口 使用官方示例中的正确接口地址
            var url = "https://cardnumber.market.alicloudapi.com/rest/160601/ocr/ocr_idcard.json";


            // 请求配置
            string side = cardType == "front" ? "face" : "back";
            string config = $"{{\"side\": \"{side}\"}}";

            // 请求体
            string bodys = $"{{\"image\":\"{imageBase64}\",\"configure\":{config}}}";

            // 创建请求
            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
            httpRequest.Method = "POST";
            httpRequest.Headers.Add("Authorization", "APPCODE " + appCode);
            httpRequest.ContentType = "application/json; charset=UTF-8";

            // 写入请求体
            byte[] data = Encoding.UTF8.GetBytes(bodys);
            using (Stream stream = httpRequest.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }

            // 获取响应
            string responseContent;
            HttpWebResponse httpResponse;

            try
            {
                httpResponse = (HttpWebResponse)httpRequest.GetResponse();
                using (Stream st = httpResponse.GetResponseStream())
                using (StreamReader reader = new StreamReader(st, Encoding.GetEncoding("utf-8")))
                {
                    responseContent = reader.ReadToEnd();
                    _logger.LogInformation($"OCR响应状态码: {httpResponse.StatusCode}");
                    _logger.LogInformation($"OCR响应内容: {responseContent}");
                }
            }
            catch (WebException ex)
            {
                httpResponse = (HttpWebResponse)ex.Response;
                if (httpResponse == null)
                {
                    _logger.LogError($"OCR请求异常: {ex.Message}");
                    return new Result<IdentityCardInfo>($"OCR请求异常: {ex.Message}");
                }

                using (Stream st = httpResponse.GetResponseStream())
                using (StreamReader reader = new StreamReader(st, Encoding.GetEncoding("utf-8")))
                {
                    responseContent = reader.ReadToEnd();
                    _logger.LogError($"OCR请求失败: {httpResponse.StatusCode}, {responseContent}");
                    return new Result<IdentityCardInfo>($"OCR请求失败: {httpResponse.StatusCode}");
                }
            }

            var ocrResponse = JsonSerializer.Deserialize<AliyunOcrResponse>(responseContent);

            if (ocrResponse == null || !ocrResponse.success)
            {
                return new Result<IdentityCardInfo>("身份证识别失败，未检测到身份证信息");
            }

            var result = new IdentityCardInfo();

            // 解析正面信息
            if (cardType == "front")
            {
                result.Name = ocrResponse.name;
                result.Gender = ocrResponse.sex; // 使用sex字段
                result.Nationality = ocrResponse.nationality;
                result.BirthDate = ocrResponse.birth;
                result.Address = ocrResponse.address;
                result.IdNumber = ocrResponse.num;
                if (string.IsNullOrWhiteSpace(result.IdNumber))
                {
                    return new Result<IdentityCardInfo>("身份证正面识别失败，未检测到身份证号");
                }
            }
            // 解析背面信息
            else if (cardType == "back")
            {
                result.IssuingAuthority = ocrResponse.issue;
                // 根据官方文档，背面有start_date和end_date字段
                if (!string.IsNullOrEmpty(ocrResponse.start_date) && !string.IsNullOrEmpty(ocrResponse.end_date))
                {
                    result.ValidPeriod = $"{ocrResponse.start_date}-{ocrResponse.end_date}";

                    // 解析身份证到期时间
                    if (ocrResponse.end_date.Contains("长期") ||
                        ocrResponse.end_date.Contains("永久") ||
                        ocrResponse.end_date.Contains("长久"))
                    {
                        // 长期有效设置为100年后
                        result.IdCardExpiryDate = DateTime.Now.AddYears(100);
                    }
                    else
                    {
                        // 尝试解析具体日期
                        if (DateTime.TryParseExact(ocrResponse.end_date, "yyyyMMdd", null, DateTimeStyles.None,
                                out DateTime expiryDate) ||
                            DateTime.TryParseExact(ocrResponse.end_date, "yyyy.MM.dd", null, DateTimeStyles.None,
                                out expiryDate) ||
                            DateTime.TryParseExact(ocrResponse.end_date, "yyyy年MM月dd日", null, DateTimeStyles.None,
                                out expiryDate) ||
                            DateTime.TryParseExact(ocrResponse.end_date, "yyyy-MM-dd", null, DateTimeStyles.None,
                                out expiryDate))
                        {
                            result.IdCardExpiryDate = expiryDate;
                        }
                        else
                        {
                            _logger.LogWarning($"无法解析身份证到期时间格式: {ocrResponse.end_date}");
                        }
                    }
                }

                if (result.IdCardExpiryDate == null)
                {
                    return new Result<IdentityCardInfo>("身份证反面识别失败，未检测到有效期");
                }
            }

            return new Result<IdentityCardInfo>
            {
                Code = 200,
                Message = "身份证识别成功",
                Data = result
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "身份证识别异常");
            return new Result<IdentityCardInfo>($"身份证识别异常：{ex.Message}");
        }
    }


    // 阿里身份证OCR文字识别：https://help.aliyun.com/zh/ocr/developer-reference/api-ocr-api-2021-07-07-recognizeidcard?spm=a2c4g.11186623.0.i0
    public async Task<Result<IdentityCardInfo>> RecognizeAsync(Guid ImageId, string cardType = "front")
    {
        try
        {
            _logger.LogInformation($"开始识别身份证，ImageId: {ImageId}, cardType: {cardType}");

            var scope = _context.ServiceProvider.CreateScope();
            var dc = scope.ServiceProvider.GetRequiredService<WTMContext>().DC;
            var fileAttachment = await dc.Set<FileAttachment>()
                .AsNoTracking()
                .FirstOrDefaultAsync(f => f.ID == ImageId);

            if (fileAttachment == null)
            {
                _logger.LogWarning($"未找到图片，ImageId: {ImageId}");
                return new Result<IdentityCardInfo>("图片不存在");
            }

            byte[] imageData = null;
            
            _logger.LogInformation($"图片存储模式: {fileAttachment.SaveMode}");
            // 根据存储类型获取图片数据
            if (string.Equals(fileAttachment.SaveMode, "database", StringComparison.OrdinalIgnoreCase))
            {
                // 数据库存储模式
                if (fileAttachment.FileData == null || fileAttachment.FileData.Length == 0)
                {
                    _logger.LogWarning($"数据库存储的图片内容为空，ImageId: {ImageId}");
                    return new Result<IdentityCardInfo>("数据库存储的图片内容为空");
                }

                imageData = fileAttachment.FileData;
            }
            else if (string.Equals(fileAttachment.SaveMode, "local", StringComparison.OrdinalIgnoreCase))
            {
                // 本地文件存储模式
                if (string.IsNullOrEmpty(fileAttachment.Path))
                {
                    _logger.LogWarning($"本地存储的图片路径为空，ImageId: {ImageId}");
                    return new Result<IdentityCardInfo>("本地存储的图片路径为空");
                }

                var fullPath = Path.IsPathRooted(fileAttachment.Path)
                    ? fileAttachment.Path
                    : Path.Combine(Directory.GetCurrentDirectory(), fileAttachment.Path);

                if (!File.Exists(fullPath))
                {
                    _logger.LogWarning($"本地图片文件不存在，路径: {fullPath}");
                    return new Result<IdentityCardInfo>($"本地图片文件不存在: {fileAttachment.Path}");
                }

                try
                {
                    imageData = await File.ReadAllBytesAsync(fullPath);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, $"读取本地图片文件失败，路径: {fullPath}");
                    return new Result<IdentityCardInfo>($"读取本地图片文件失败: {ex.Message}");
                }
            }
            else
            {
                _logger.LogWarning($"不支持的存储模式: {fileAttachment.SaveMode}，ImageId: {ImageId}");
                return new Result<IdentityCardInfo>($"不支持的存储模式: {fileAttachment.SaveMode}");
            }

            if (imageData == null || imageData.Length == 0)
            {
                _logger.LogWarning($"获取到的图片数据为空，ImageId: {ImageId}");
                return new Result<IdentityCardInfo>("图片数据为空");
            }

            var siteConfig = _context.GetSiteConfig();
            var accessKeyId = siteConfig.AliyunOcrAppKey;
            var accessKeySecret = siteConfig.AliyunOcrAppSecret;

            var config = new AlibabaCloud.OpenApiClient.Models.Config
            {
                AccessKeyId = accessKeyId,
                AccessKeySecret = accessKeySecret,
                Endpoint = "ocr-api.cn-hangzhou.aliyuncs.com"
            };
            var client = new AlibabaCloud.OpenApiClient.Client(config);

            var params_ = new Params
            {
                Action = "RecognizeIdcard",
                Version = "2021-07-07",
                Protocol = "HTTPS",
                Method = "POST",
                AuthType = "AK",
                Style = "V3",
                Pathname = "/",
                ReqBodyType = "binary",
                BodyType = "json"
            };

            using var imageStream = new MemoryStream(imageData);
            var request = new OpenApiRequest
            {
                Stream = imageStream,
                Query = new Dictionary<string, string>
                {
                    { "Side", cardType == "front" ? "face" : "back" }
                }
            };

            var runtime = new RuntimeOptions();
            _logger.LogInformation("即将调用阿里云OCR接口...");
            var response = await client.CallApiAsync(params_, request, runtime);
            var body = response["body"];
            //_logger.LogInformation($"阿里云OCR接口响应: {JsonSerializer.Serialize(response)}");

            Dictionary<string, JsonElement> root = null;
            if (body is JsonElement je)
            {
                root = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(je.GetRawText());
            }
            else if (body is string str)
            {
                root = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(str);
            }
            else
            {
                var json = JsonSerializer.Serialize(body);
                root = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json);
            }

            // 错误处理
            if (root.TryGetValue("Code", out var code) && code.ValueKind != JsonValueKind.Undefined &&
                code.ValueKind != JsonValueKind.Null)
            {
                var msg = root.TryGetValue("Message", out var message) ? message.GetString() : "识别失败";
                _logger.LogWarning($"阿里云OCR返回错误，Code: {code}, Message: {msg}");
                return new Result<IdentityCardInfo>($"识别失败: {msg}");
            }

            if (!root.TryGetValue("Data", out var dataElement) || dataElement.ValueKind == JsonValueKind.Null)
            {
                _logger.LogWarning("阿里云OCR响应未返回有效Data字段");

                return new Result<IdentityCardInfo>("未返回有效Data字段");
            }

            // Data 可能是字符串，需要再次反序列化
            Dictionary<string, JsonElement> dataObj = null;
            if (dataElement.ValueKind == JsonValueKind.String)
            {
                dataObj = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(dataElement.GetString());
            }
            else
            {
                dataObj = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(dataElement.GetRawText());
            }

            // 关键：先取 dataObj["data"]
            if (!dataObj.TryGetValue("data", out var innerDataElement) ||
                innerDataElement.ValueKind == JsonValueKind.Null)
            {
                _logger.LogWarning("阿里云OCR响应未返回有效data字段");
                return new Result<IdentityCardInfo>("未返回有效data字段");
            }

            var innerDataObj =
                JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(innerDataElement.GetRawText());

            var result = new IdentityCardInfo();

            if (cardType == "front")
            {
                if (innerDataObj.TryGetValue("face", out var faceElement))
                {
                    var face = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(faceElement.GetRawText());
                    if (face != null && face.TryGetValue("data", out var faceDataElement))
                    {
                        var faceData =
                            JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(faceDataElement.GetRawText());
                        result.Name = faceData.TryGetValue("name", out var name) ? name.GetString() : null;
                        result.Gender = faceData.TryGetValue("sex", out var sex) ? sex.GetString() : null;
                        result.Nationality = faceData.TryGetValue("ethnicity", out var eth) ? eth.GetString() : null;
                        result.BirthDate = faceData.TryGetValue("birthDate", out var birth) ? birth.GetString() : null;
                        result.Address = faceData.TryGetValue("address", out var addr) ? addr.GetString() : null;
                        result.IdNumber = faceData.TryGetValue("idNumber", out var id) ? id.GetString() : null;
                    }
                }

                if (string.IsNullOrWhiteSpace(result.IdNumber))
                {
                    _logger.LogWarning("身份证正面识别失败，未检测到身份证号");
                    return new Result<IdentityCardInfo>("身份证正面识别失败，未检测到身份证号");
                }
            }
            else if (cardType == "back")
            {
                if (innerDataObj.TryGetValue("back", out var backElement))
                {
                    var back = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(backElement.GetRawText());
                    if (back != null && back.TryGetValue("data", out var backDataElement))
                    {
                        var backData =
                            JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(backDataElement.GetRawText());
                        result.IssuingAuthority =
                            backData.TryGetValue("issueAuthority", out var issue) ? issue.GetString() : null;
                        var validPeriod = backData.TryGetValue("validPeriod", out var period)
                            ? period.GetString()
                            : null;

                        // 解析身份证到期时间
                        if (!string.IsNullOrEmpty(validPeriod))
                        {
                            var parts = validPeriod.Split('-');
                            if (parts.Length == 2)
                            {
                                var endDateStr = parts[1].Trim();
                                if (endDateStr.Contains("长期") || endDateStr.Contains("永久") || endDateStr.Contains("长久"))
                                {
                                    // 长期有效设置为100年后
                                    result.IdCardExpiryDate = DateTime.Now.AddYears(100);
                                }
                                else
                                {
                                    // 尝试解析具体日期
                                    if (DateTime.TryParseExact(endDateStr, "yyyyMMdd", null, DateTimeStyles.None,
                                            out DateTime expiryDate) ||
                                        DateTime.TryParseExact(endDateStr, "yyyy.MM.dd", null, DateTimeStyles.None,
                                            out expiryDate) ||
                                        DateTime.TryParseExact(endDateStr, "yyyy年MM月dd日", null, DateTimeStyles.None,
                                            out expiryDate) ||
                                        DateTime.TryParseExact(endDateStr, "yyyy-MM-dd", null, DateTimeStyles.None,
                                            out expiryDate))
                                    {
                                        result.IdCardExpiryDate = expiryDate;
                                    }
                                    else
                                    {
                                        _logger.LogWarning($"无法解析身份证到期时间格式: {endDateStr}");
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        return new Result<IdentityCardInfo>("未能识别到有效期");
                    }
                }

                if (result.IdCardExpiryDate == null)
                {
                    return new Result<IdentityCardInfo>("身份证反面识别失败，未检测到有效期");
                }
            }

            return new Result<IdentityCardInfo>
            {
                Code = 200,
                Message = "身份证识别成功",
                Data = result
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "身份证识别异常");
            return new Result<IdentityCardInfo>($"身份证识别异常：{ex.Message}");
        }
    }
}